package com.open.capacity.user.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.open.capacity.commons.CodeEnum;
import com.open.capacity.commons.PageResult;
import com.open.capacity.commons.Result;
import com.open.capacity.easypoi.user.SysUserExcel;
import com.open.capacity.prints.excel.KjkmExcelModel;
import com.open.capacity.prints.util.uuid.UUIDUtils;
import com.open.capacity.model.system.LoginAppUser;
import com.open.capacity.model.system.SysRole;
import com.open.capacity.model.system.SysUser;
import com.open.capacity.model.system.constants.UserType;
import com.open.capacity.user.dao.SysRoleDao;
import com.open.capacity.user.dao.SysUserDao;
import com.open.capacity.user.model.SysUserRelation;
import com.open.capacity.user.service.SysUserRelationService;
import com.open.capacity.user.service.SysUserService;
import com.open.capacity.user.vo.SysUserVo;
import com.open.capacity.utils.*;
import com.open.capacity.vo.SysUserRelationExtVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

/**
 * @author 作者 ftquan E-mail: 464725602@qq.com
 * @version 创建时间：2017年11月12日 上午22:57:51
 */
@Slf4j
@Service
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserDao userDao;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private SysRoleDao roleDao;
    @Autowired
    private SysUserRelationService userRelationService;

    @Autowired(required = false)
    private TokenStore redisTokenStore;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysUser updateSysUser(SysUser sysUser) {
        sysUser.setUpdateTime(new Date());

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if (authentication instanceof OAuth2Authentication) {
            OAuth2Authentication oAuth2Auth = (OAuth2Authentication) authentication;
            authentication = oAuth2Auth.getUserAuthentication();

            OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) oAuth2Auth.getDetails();

            LoginAppUser user = SysUserUtil.getLoginAppUser();

            if (user != null) {

                if (!ObjectUtils.notEqual(user.getId(), sysUser.getId())) {

                    OAuth2AccessToken token = redisTokenStore.readAccessToken(details.getTokenValue());

                    if (token != null) {

                        if (!StringUtils.isBlank(sysUser.getHeadUrl())) {
                            user.setHeadUrl(sysUser.getHeadUrl());
                        }

                        if (!StringUtils.isBlank(sysUser.getNewPassword())) {
                            user.setPassword(sysUser.getNewPassword());
                        }

                        if (!StringUtils.isBlank(sysUser.getNewPassword())) {
                            user.setPassword(sysUser.getNewPassword());
                        }

                        if (!StringUtils.isBlank(sysUser.getNickName())) {
                            user.setNickName(sysUser.getNickName());
                        }

                        if (!StringUtils.isBlank(sysUser.getPhone())) {
                            user.setPhone(sysUser.getPhone());
                        }

                        if (sysUser.getSex() != null) {
                            user.setSex(sysUser.getSex());
                        }

                        UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken(user,
                                null, user.getAuthorities());

                        OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Auth.getOAuth2Request(), userAuthentication);
                        oAuth2Authentication.setAuthenticated(true);
                        redisTokenStore.storeAccessToken(token, oAuth2Authentication);

                    }

                }

            }
        }

        userDao.updateByOps(sysUser);
        log.info("修改用户：{}", sysUser);
        return sysUser;
    }

    @Override
    public SysUserRelationExtVo findUserRelationsByObjectId(String objectId) {
        SysUserRelationExtVo vo = new SysUserRelationExtVo();
        List<SysUserRelation> list = userRelationService.findByObjectId(objectId);
        String userIds = "";
        Set<SysUser> userSet = new HashSet<>();
        for (SysUserRelation item : list) {
            if (userIds != "") {
                userIds += ",";
            }
            userIds += item.getUserId();
            userSet.add(userDao.findById(item.getUserId()));
        }
        vo.setUserInfoList(userSet);
        vo.setUserIds(userIds);
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public LoginAppUser findByUsername(String username) {
        SysUser sysUser = userDao.findByUsername(username);
        if (sysUser == null) {
            return null;
        }
        List<SysUserRelation> list = userRelationService.findByUserId(sysUser.getId());
        String postIds = "", roleIds = "";
        if (!CollectionUtils.isEmpty(list)) {
            for (SysUserRelation relation : list) {
                if (relation.getObjectType().toLowerCase().equals("role")) {
                    if (roleIds.length() == 0) {
                        roleIds += relation.getObjectId();
                    } else {
                        roleIds += "," + relation.getObjectId();
                    }
                } else if (relation.getObjectType().toLowerCase().equals("post")) {
                    if (postIds.length() == 0) {
                        postIds += relation.getObjectId();
                    } else {
                        postIds += "," + relation.getObjectId();
                    }
                }
            }
            sysUser.setPostIds(postIds);
            sysUser.setRoleIds(roleIds);
        }
        if (sysUser != null) {
            LoginAppUser loginAppUser = new LoginAppUser();
            BeanUtils.copyProperties(sysUser, loginAppUser);

            Set<SysRole> sysRoles = roleDao.findByUserId(sysUser.getId());
            loginAppUser.setSysRoles(sysRoles);// 设置角色

            return loginAppUser;
        }

        return null;
    }

    @Override
    public SysUser findById(String id) {
        SysUser user = userDao.findById(id);
        List<SysUserRelation> list = userRelationService.findByUserId(id);
        String postIds = "", roleIds = "";
        if (!CollectionUtils.isEmpty(list)) {
            for (SysUserRelation relation : list) {
                if (relation.getObjectType().toLowerCase().equals("role")) {
                    if (roleIds.length() == 0) {
                        roleIds += relation.getObjectId();
                    } else {
                        roleIds += "," + relation.getObjectId();
                    }
                } else if (relation.getObjectType().toLowerCase().equals("post")) {
                    if (postIds.length() == 0) {
                        postIds += relation.getObjectId();
                    } else {
                        postIds += "," + relation.getObjectId();
                    }
                }
            }
            user.setPostIds(postIds);
            user.setRoleIds(roleIds);
        }
        return user;


    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result updatePassword(String id, String oldPassword, String newPassword) {
        SysUser sysUser = userDao.findById(id);
        if (StringUtils.isNoneBlank(oldPassword)) {
            if (!passwordEncoder.matches(oldPassword, sysUser.getPassword())) {
                return Result.failed("旧密码错误");
            }
        }

        SysUser user = new SysUser();
        user.setId(id);
        user.setPassword(passwordEncoder.encode(newPassword));

        updateSysUser(user);
        log.info("修改密码：{}", user);
        return Result.succeed("修改成功");
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result updateStatus(String id, Integer status) {
        SysUser user = new SysUser();
        user.setId(id);
        user.setStatus(status);
        updateSysUser(user);
        log.info("修改状态：{}", user);
        return Result.succeed("修改成功");
    }

    @Override
    public List<SysUser> findUsers(Map<String, Object> params) {
        return userDao.findList(params);
    }


    @Override
    public PageResult<SysUser> pageUsers(Map<String, Object> params) {
        int total = userDao.count(params);
        List<SysUser> list = Collections.emptyList();
        if (total > 0) {
            PageUtil.pageParamConver(params, true);
            list = userDao.findList(params);
        }
        return PageResult.<SysUser>builder().data(list).resp_code(CodeEnum.SUCCESS.getCode()).count((long) total).build();
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result saveOrUpdate(SysUser sysUser, String keyValue) {
        String username = sysUser.getUserName();
        if (StringUtils.isBlank(username)) {
            //throw new IllegalArgumentException("用户名不能为空");
            return Result.failed("用户名不能为空");
        }

        if (ValidatorUtil.checkPhone(username)) {// 防止用手机号直接当用户名，手机号要发短信验证
            //throw new IllegalArgumentException("用户名要包含英文字符");
            return Result.failed("用户名要包含英文字符");
        }

        if (username.contains("@")) {// 防止用邮箱直接当用户名，邮箱也要发送验证（暂未开发）
            //throw new IllegalArgumentException("用户名不能包含@");
            return Result.failed("用户名不能包含@");
        }

        if (username.contains("|")) {
            //throw new IllegalArgumentException("用户名不能包含|字符");
            return Result.failed("用户名不能包含|字符");
        }

        if (StringUtils.isBlank(sysUser.getNickName())) {
            sysUser.setNickName(username);
        }

        if (StringUtils.isBlank(sysUser.getType())) {
            sysUser.setType(UserType.BACKEND.name());
        }

        if (!StringUtils.isBlank(sysUser.getPhone())) {
            if (!ValidatorUtil.checkPhone(sysUser.getPhone())) {// 防止用手机号直接当用户名，手机号要发短信验证
                //throw new IllegalArgumentException("用户名要包含英文字符");
                return Result.failed("手机号格式不正确");
            }
        }

        sysUser.setPassword(passwordEncoder.encode("123456"));
        sysUser.setStatus(1);
        sysUser.setCreateTime(new Date());

        int i;
        if (StringUtils.isEmpty(keyValue)) {
            SysUser persistenceUser = userDao.findByUsername(sysUser.getUserName());
            if (persistenceUser != null && persistenceUser.getUserName() != null) {
                //throw new IllegalArgumentException("用户名已存在");
                return Result.failed("用户名已存在");
            }
            sysUser.setId(UUIDUtils.getOriginalUUIDWithoutBar());
            sysUser.setUpdateTime(sysUser.getCreateTime());
            i = userDao.insert(sysUser);
        } else {
            sysUser.setId(keyValue);
            sysUser.setUpdateTime(new Date());
            i = userDao.updateByOps(sysUser);
        }

//		userRoleDao.deleteUserRole(sysUser.getId(), null);
//		List roleIds = Arrays.asList(sysUser.getRoleId().split(","));
//		if (!CollectionUtils.isEmpty(roleIds)) {
//			roleIds.forEach(roleId -> {
//				userRoleDao.saveUserRoles(sysUser.getId(), Long.parseLong(roleId.toString()));
//			});
//		}

        return i > 0 ? Result.succeed(sysUser, "操作成功") : Result.failed("操作失败");
    }

    @Override
    public List<SysUserExcel> findAllUsers(Map<String, Object> params) {
        List<SysUserExcel> sysUserExcels = new ArrayList<>();
        List<SysUser> list = userDao.findList(params);

        for (SysUser sysUser : list) {
            SysUserExcel sysUserExcel = new SysUserExcel();
            BeanUtils.copyProperties(sysUser, sysUserExcel);
            sysUserExcels.add(sysUserExcel);
        }
        return sysUserExcels;
    }

    @Override
    public Map<String, SysUserVo> getMap() {
        Map<String, SysUserVo> map = new HashMap<>();
        Map<String, Object> params = new HashMap<>();
        List<SysUser> list = userDao.findList(params);
        SysUserVo vo;
        for (SysUser item : list) {
            vo = new SysUserVo();
            vo.setCompanyId(item.getCompanyId());
            vo.setDepartmentId(item.getDepartmentId());
            vo.setName(item.getRealName());
            map.put(item.getId(), vo);
        }
        return map;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int importExcel(MultipartFile multipartFile, String companyId) throws Exception {
        ImportParams params = new ImportParams();
        params.setHeadRows(1);
        // params.setTitleRows(0);
        // 开启excel校验
        params.setNeedVerify(true);

        ExcelImportResult<KjkmExcelModel> result = new ExcelImportResult();
        try {
            result = ExcelImportUtil.importExcelMore(multipartFile.getInputStream(),
                    KjkmExcelModel.class, params);
        } catch (Exception e) {

            log.error("从文件读取数据错误:{}", e.getMessage());
        }
        if (result.isVerifyFail()) {
            StringBuilder temp = new StringBuilder();
            for (KjkmExcelModel entity : result.getFailList()) {
                temp.append("第").append(entity.getRowNum()).append("行的错误是：").append(entity.getErrorMsg());
            }
            throw new Exception("Excel文件校验不通过:" + temp.toString());
        }


        return result.getList().size();
    }
}
